# -*- coding: utf-8 -*-
# ficheiro: aula2.py
# autor: João Rebocho- 6035
# data: 30 de setembro de 2013
# obs.: primeiro programa realizado em python

print "Hello World"
a = 99
print a
a = a + 77

if a > 10:
    print "maior do que 10"
    print "de novo"

print "-------------------------------------------"

print type(1), type(3.4), type((3 + 3j) + 2)
print type('treta'), type(True and False)
a = '1'
b = 'uma'
print type(a), type(b)
print type([1, 2, 3 ,[2, 3]]) , type((1, 2, 3))

class Teste:
    pass

print type(Teste)
obj = Teste()
print type(obj)

def func():
    return 3

print type(func)

print type(range(0, 10))
print type(xrange(0, 10))
print type(a > 10 if 10 else 2)
print type(a) == type('string') if "uma string" else "não sei"

c = 3 + (3 + 3j)
print type(c) == type(3 + 3j) if "complexo" else "não sei"


print "-------------------------------------------"

'''
representação de inteiros
'''

#soma de um par de hexadecimais
#declaração de duas varioaveis do tipo 'str'
a = '0xa' #representção corrempondente ao numero inteiro 10
b = '0xb' #representção corrempondente ao numero inteiro 11

#conversão da representacao em termos de 'str' em inteiro
#encolhendo a base hexadecimal 16
base = 16
a_int = int(a, base)
b_int = int(b, base)

#soma dos inteiros resultantes
c_int = a_int + b_int

#conversao na representacao hexadecimal em termos de 'str'
c = hex(c_int)

#impressao no ecran do resultado
print c

#representação do numero binario corrempondente a 
b = '0b11110001'

#conversão para hexadecimal e impressao no ecram
print hex(int(b,2))

#representacao de numeros complexos
#conversao de complexos em coordenadas polares

#esta declaracao declara publico na aplicacao
#o espaco de nomes math

import math

#declaracao de um numero complexo
#com parte real := 3
#e parte imaginaria := 6

c = 3 + 6j

print c
print c.imag, c.real


a = c.real
b = c.imag

#modulo do numero complexo
r = math.sqrt(a ** 2 + b**2)
print 'modulo = {0}'.format(r)

#calculo alternativo do modulo
r = (a**2 + b**2) ** 0.5
print 'modulo = {0}'.format(r)

#calculo do argumento theta
t = math.atan2(b, a)

#conversao de radianos para graus
print t * 180.0 /math.pi

#verificacao das diferencas entre atan2() e atan()
print math.atan2(-2, -2), math.atan2(2,2)
print math.atan(-2/ -2), math.atan(2/2)
print "-------------------------------------------"


#Operacoes com caracteres
#Conversao de caracteres

l1 = [2, 2, 3, 4]
l2 = ['sjfdlkjsdlisf', 'kjslfds']
l3 = [l1, l2]
l4 = list('Uma carrada de erros')

print l4

#eleminacao de erros de l4 e conversao na string s5
#tecnica numero um 
#programacao imperativa
s5 = ''
for x in l4:
    if x == r:
        pass
    else:
        s5 += x
        pass
    pass
print s5

#tecnica numero dois
#programacao funcional
s6 = reduce(lambda x, y: x+ y, filter(lambda x: x!= 'r', l4))

print s6

print "-------------------------------------------"

import random
#selecao de valores pares e impares

#criação de uma lista de 20 numeros inteiros aleatorios
#distribuidos uniformemente entre 0 e 99
l1 = list()
N = 20
k = 0
while k < N:
    l1.append(random.randint(0, 99))
    k += 1
    pass

#lista dos numeros pares
l2 = list()
for x in l1:
    if not(x % 2):
        l2.append(x)
        pass
    pass

#abordagem funcional
#criacao da lista de dados por uso de uma compreensao de lista
l1 = [ random.randint(0, 99) for k in range(N)]

#uso de um filtro com expressoes lambda
l2 = filter(lambda x: not(x%2), l1)

print "-------------------------------------------"

#n-ésimo valor de um serie
#abordagem imperativa
def serie_iter(n):
    '''
    serie geometrica
    '''
    k = 0
    soma = 0.0
    
    while k <= n:
        soma += 1.0 / (2.0 ** k)
        k += 1
        pass
    return soma

#abordagem funcional
def serie_fun(n):
    if n == 0:
        return 0.0
    else:
        return 1.0 / (2 ** k) + serie_fun(n-1)

#abordagem funcional 2
#usando os recursos da linguagem Python

def serie_fun2(n):
    return reduce(lambda x, k: x + 1.0 / (2.0 ** k), range(0, n +1))

for k in range(21):
    print k, serie_iter(k), serie_fun(k), serie_fun2(k)


print "-------------------------------------------"

'''
Soma integral
realização de uma versao iterativa de um programa de calculo de
integrais de forma iterativa
'''

def soma_integral(f, a, b):
    '''
    comentarios sobre a funcao
    soma_integral()- soma integral de uma funcao  pela regra do trapezio
    f - funcao unidimensional a integrar
    a - limite inferior
    b - limite superior
    '''

    #numero de intervalos
    N = 500

    #aproximacao ao infinitesimo
    #conversao para numeros reais
    dx = (float(b) - float(a)) / float(N)
    
    #soma integral
    soma = 0.0
    x = a
    while x <= b:
        soma += f(x) * dx
        x += dx
        pass
    return soma

def f(x):
    return x

a = 0.0
b = 1.0
print soma_integral(f, a, b)
